package com.block.common.util;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;

import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoField;
import java.util.Calendar;
import java.util.Locale;
import java.util.TimeZone;

/**
 * 
 * 时间工具类, 使用jdk1.8 localdatetime
 */
public class LocalDateUtil {
    public static final TimeZone TIME_ZONE = TimeZone.getTimeZone("CTT");
    static final long nd = 1000 * 24 * 60 * 60;
    static final long nh = 1000 * 60 * 60;
    static final long nm = 1000 * 60;
    public static final String ATTACHMENT_DATE = "yyyyMM/dd/";
    /**
     * 整个日期时间格式
     * yyyy-MM-dd HH:mm:ss
     */
    public static final String TOTAL_DATE_TIME = "yyyy-MM-dd HH:mm:ss";
    /**
     * 整个日期时间格式(到分钟)
     * yyyy-MM-dd HH:mm
     */
    public static final String TOTAL_DATE_TIME_UNTIL_MIN = "yyyy-MM-dd HH:mm";
    /**
     * 月日+分秒
     * MM-dd HH:mm
     */
    public static final String TOTAL_DATE_TIME_NOT_YEAR = "MM-dd HH:mm";

       /**
     * 月日+分秒
     * MM-dd HH:mm
     */
    public static final String TOTAL_DATE_TIME_NOT_TIME = "MM-dd-yyyy HH:mm";

       /**
     * 月日+分秒
     * MM-dd HH:mm
     */
    public static final String TOTAL_DATE_TIME_NOT_DATE = "MM-dd-yyyy ";

    /**
     * 整个日期时间格式(没杠和分好空格，含毫秒
     * yyyyMMddHHmmssSSS
     */
    public static final String TOTAL_DATE_TIME_SIMPLE_SECOND = "yyyyMMddHHmmssSSS";
    /**
     * 整个日期时间格式【简化版】
     * yyyyMMddHHmmss
     */
    public static final String TOTAL_DATE_TIME_SIMPLE = "yyyyMMddHHmmss";
    /**
     * 整个日期时间格式【日期没有杠的版本】
     * yyyyMMdd HH:mm:ss
     */
    public static final String TOTAL_DATE_TIME_NOT_GANG = "yyyyMMdd HH:mm:ss";
    /**
     * 整个日期时间格式【中间没有空格的版本】
     * yyyy-MM-ddHH:mm:ss
     */
    public static final String TOTAL_DATE_TIME_NOT_SPACE = "yyyy-MM-ddHH:mm:ss";
    /**
     * 整个日期时间格式【有毫秒】
     * yyyy-MM-dd HH:mm:ss SSS
     */
    public static final String TOTAL_DATE_TIME_SSS = "yyyy-MM-dd HH:mm:ss SSS";
    /**
     * 整个日期时间格式【有毫秒】
     * yyyy-MM-dd HH:mm:ss SSS
     */
    public static final String TOTAL_DATE_TIME_SSS_MYSQL = "yyyy-MM-dd HH:mm:ss.SSS";
    /**
     * 整个日期时间格式【中间没有空格的版本并且日期没有杠的版本】
     * yyyyMMddHH:mm:ss
     */
    public static final String TOTAL_DATE_TIME_NOT_SPACE_GANG = "yyyyMMddHHmmss";
    /**
     * 交易时间格式
     * MM-dd yyyy HH:mm
     */
    public static final String TRADE_HISTORY_DATE_TIME = "MM-dd yyyy HH:mm";
    /**
     * 简单时间格式
     * HH:mm:ss
     */
    public static final String SIMPLE_TIME = "HH:mm:ss";
    /**
     * 简单时间格式【没有冒号】
     * HHmmss
     */
    public static final String SIMPLE_TIME_NOT_COMMA = "HHmmss";
    /**
     * 简单年份
     * yyyy
     */
    public static final String YEAR = "yyyy";
    /**
     * 简单日期格式
     * yyyyMMdd
     */
    public static final String SIMPLE_DATE = "yyyyMMdd";
    /**
     * 简单日期格式【带杠的】
     * yyyy-MM-dd
     */
    public static final String SIMPLE_GANG_DATE = "yyyy-MM-dd";
    /**
     * 只获取月份和日期
     * MM-dd
     */
    public static final String SIMPLE_MONTH_DAY = "MM-dd";
    /**
     * 只获取日期
     */
    public static final String SIMPLE_DAY = "dd";

    private static final long ONE_MINUTE = 60L;
    private static final long ONE_HOUR = 3600L;
    private static final long ONE_DAY = 86400L;

    private static final String ONE_SECOND_AGO = "秒前";
    private static final String ONE_MINUTE_AGO = "分钟前";
    private static final String ONE_HOUR_AGO = "小时前";
    private static final String ONE_DAY_AGO = "天前";

    /**
     * 获取今日剩余秒数
     * @return
     */
    public static Long getRemainSecondNumber(){
        Long totalSecond = 24 * 60 * 60L;
        Long nowSecond = LocalDateTime.now().getLong(ChronoField.SECOND_OF_DAY);
        return totalSecond - nowSecond;
    }

    /**
     * 将字符串转为localdatetime 格式为 yyyy-MM-dd HH:mm:ss SSS
     *
     * @param dateTime
     * @return
     */
    public static LocalDateTime getDateTimeStrFormatByStr(String dateTime) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(TOTAL_DATE_TIME_SSS);
        LocalDateTime localDateTime = LocalDateTime.parse(dateTime, df);
        return localDateTime;
    }
//    DateTimeFormatter df = DateTimeFormatter.ofPattern(format);
//    String localTime = df.format(localDateTime);
    public static LocalDateTime getLongToLocalDateTime(Long time){
        LocalDateTime longToLocalDateTime =
                LocalDateTime.ofInstant(Instant.ofEpochMilli(time), TIME_ZONE.toZoneId());
        return longToLocalDateTime;
    }

    public static LocalDateTime getLongToLocalDateTime(Long time,TimeZone timeZone){
        LocalDateTime longToLocalDateTime =
                LocalDateTime.ofInstant(Instant.ofEpochMilli(time), timeZone.toZoneId());
        return longToLocalDateTime;
    }
    public static String getLongToLocalDateTimeFmt(Long time,String fmt){
        LocalDateTime longToLocalDateTime =
                LocalDateTime.ofInstant(Instant.ofEpochMilli(time), TIME_ZONE.toZoneId());
        return  LocalDateUtil.getDateFormatStr(longToLocalDateTime,fmt);
    }

    public static String getLongToLocalDateTimeFmtUTC(Long time){
        LocalDateTime longToLocalDateTime =
                LocalDateTime.ofInstant(Instant.ofEpochMilli(time), TIME_ZONE.toZoneId());
        return  LocalDateUtil.getDateFormatStr(longToLocalDateTime,TRADE_HISTORY_DATE_TIME);
    }

    public static String getLongToLocalDateTimeFmt(Long time,String fmt,TimeZone timeZone){
        LocalDateTime longToLocalDateTime =
                LocalDateTime.ofInstant(Instant.ofEpochMilli(time), timeZone.toZoneId());
        return LocalDateUtil.getDateFormatStr(longToLocalDateTime,fmt);
    }
    /**
     * 将字符串转为localdatetime 格式为 yyyy-MM-dd HH:mm:ss SSS
     *
     * @param dateTime
     * @return
     */
    public static LocalDateTime getDateTimeByStr(String dateTime) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(TOTAL_DATE_TIME_SSS);
        LocalDateTime localDateTime = LocalDateTime.parse(dateTime, df);
        return localDateTime;
    }

    /**
     * 将一个格式的日期转为另一个格式 只要日期 不用时间
     *
     * @param dateTime
     * @param originFmt
     * @param toFmt
     * @return
     */
    public static String LocalDateFmtToOtherStr(String dateTime, String originFmt, String toFmt) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(originFmt);
        LocalDate localDate = LocalDate.parse(dateTime, df);
        DateTimeFormatter df2 = DateTimeFormatter.ofPattern(toFmt);
        return localDate.format(df2);
    }

    /**
     * 将一个格式的日期转为另一个格式 必须要有日期+时间
     *
     * @param dateTime
     * @param originFmt
     * @param toFmt
     * @return
     */
    public static String DateFmtToOther(String dateTime, String originFmt, String toFmt) {
        if (StrUtil.isEmpty(dateTime)) {
            return null;
        }
        DateTimeFormatter df = DateTimeFormatter.ofPattern(originFmt);
        LocalDateTime localDateTime = LocalDateTime.parse(dateTime, df);
        DateTimeFormatter df2 = DateTimeFormatter.ofPattern(toFmt);
        return df2.format(localDateTime);
    }

    /**
     * 将字符串转为localdatetime 格式为指定格式
     *
     * @param dateTime
     * @param format
     * @return
     */
    public static LocalDateTime getDateTimeByStr(String dateTime, String format) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(format);
        LocalDateTime localDateTime = LocalDateTime.parse(dateTime, df);
        return localDateTime;
    }

    public static LocalTime getTimeByStr(String time, String format) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(format);
        LocalTime localDateTime = LocalTime.parse(time, df);
        return localDateTime;
    }

    /**
     * 获取当前时间 返回字符串 指定格式
     *
     * @param format
     * @param format
     * @return
     */
    public static String getNowDateStr(String format) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(format);
        LocalDateTime time = LocalDateTime.now();
        String localTime = df.format(time);
        return localTime;
    }

    /**
     * 格式化时间
     *
     * @param localDateTime
     * @param format
     * @return
     */
    public static String getDateFormatStr(LocalDateTime localDateTime, String format) {
        if (localDateTime == null) {
            return null;
        }
        DateTimeFormatter df = DateTimeFormatter.ofPattern(format);
        String localTime = df.format(localDateTime);
        return localTime;
    }

    /**
     * 获取当前时间 返回字符串 指定格式 默认 yyyy-MM-dd HH:mm:ss SSS 格式
     *
     * @return
     */
    public static String getNowDateStr() {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(TOTAL_DATE_TIME_SSS);
        LocalDateTime time = LocalDateTime.now();
        String localTime = df.format(time);
        return localTime;
    }

    public static String getNowSimpleTime() {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(SIMPLE_TIME);
        LocalDateTime time = LocalDateTime.now();
        String localTime = df.format(time);
        return localTime;
    }

    /**
     * 获取当前时间 返回字符串 指定格式 默认 yyyy-MM-dd HH:mm:ss格式
     *
     * @return
     */
    public static String getNowDateStrByTotalDataTime() {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(TOTAL_DATE_TIME);
        LocalDateTime time = LocalDateTime.now();
        String localTime = df.format(time);
        return localTime;
    }


    /**
     * 【秒数比较】
     * 【当前时刻】和【传入时刻】比较
     * true -> 【当时时刻】超过【传入时刻】
     *
     * @param time 【秒单位】
     * @return
     */
    public static boolean compareNowAndTimeBySecond(long time) {
        return System.currentTimeMillis() / 1000 - time > 0;
    }

    /**
     * 当前毫秒时间戳 + 指定分钟数
     * 【返回（int）】
     * 返回：【秒数】
     *
     * @param minuteNum
     * @return 2016年11月22日 下午3:11:24
     */
    public static int getTimeAddMinute(int minuteNum) {
        return Integer.parseInt(((System.currentTimeMillis() + (minuteNum * 60 * 1000)) / 1000) + "");
    }

    /**
     * 指定时间 添加指定天数
     *
     * @param localDateTime 指定时间
     * @param day
     * @return
     */
    public static LocalDateTime getAddDays(LocalDateTime localDateTime, int day) {
        return localDateTime.plusDays(day);

    }

    /**
     * 指定时间 添加指定分钟
     *
     * @param localDateTime 指定时间
     * @param minute
     * @return
     */
    public static LocalDateTime getAddminute(LocalDateTime localDateTime, int minute) {
        return localDateTime.plusMinutes(minute);

    }

    /**
     * 指定时间 添加指定秒数
     *
     * @param localDateTime 指定时间
     * @param second
     * @return
     */
    public static LocalDateTime getAddSecond(LocalDateTime localDateTime, long second) {
        return localDateTime.plusSeconds(second);

    }

    /**
     * 指定时间 添加指定分钟
     *
     * @param localDateTime 指定时间
     * @param minute
     * @return
     */
    public static String getAddminute(LocalDateTime localDateTime, int minute, String format) {
        LocalDateTime localDateTime1 = localDateTime.plusMinutes(minute);
        return getDateFormatStr(localDateTime1, format);
    }

    /**
     * 当前时间 添加指定分钟
     *
     * @param minute
     * @param format 格式化
     * @return
     */
    public static String getNowAddminute(int minute, String format) {
        LocalDateTime localDateTime1 = LocalDateTime.now().plusMinutes(minute);
        return getDateFormatStr(localDateTime1, format);
    }

    /**
     * 当前时间加指定天数
     *
     * @param hours
     * @return
     */
    public static LocalDateTime getNowAddHours(long hours) {
        LocalDateTime localDateTime = LocalDateTime.now();
        return localDateTime.plusHours(hours);
    }

    /**
     * 当前时间加指定天数
     *
     * @param day
     * @return
     */
    public static LocalDateTime getNowAddDays(int day) {
        LocalDateTime localDateTime = LocalDateTime.now();
        return localDateTime.plusDays(day);
    }

    /**
     * 当前时间
     *
     * @return
     */
    public static LocalDate getNow() {
        return LocalDate.now();
    }


    /**
     * 把秒转换成天
     *
     * @param second
     * @return
     */
    public static Long getSecondByDay(long second) {
        long dayNum = second / nd;
        return dayNum;
    }

    /**
     * 两个时间相减获取秒差值
     *
     * @param beginDate 开始时间
     * @param endDate   结束时间
     * @return
     */
    public static Long subtractTime(LocalDateTime beginDate, LocalDateTime endDate) {
        long beginTime = beginDate.toInstant(ZoneOffset.of(getZoneStr(TIME_ZONE))).getEpochSecond();
        long endTime = endDate.toInstant(ZoneOffset.of(getZoneStr(TIME_ZONE))).getEpochSecond();
        return endTime - beginTime;
    }


    /**
     * 获取当前时间毫秒数
     *
     * @param
     * @return
     * 
     * @Date 10:16 上午 2020/10/29
     **/
    public static Long getNowByTimeMillis() {

        return LocalDateTime.now().toInstant(ZoneOffset.of(getZoneStr(TIME_ZONE))).toEpochMilli();
    }
    public static Long getTimeMillis(LocalDateTime localDateTime) {
        if (ObjectUtil.isEmpty(localDateTime)){
            return getNowByTimeMillis();
        }
        return localDateTime.toInstant(ZoneOffset.of(getZoneStr(TIME_ZONE))).toEpochMilli();
    }

    public static Long getNowByTimeSeconds() {
        return LocalDateTime.now().toInstant(ZoneOffset.of(getZoneStr(TIME_ZONE))).toEpochMilli()/1000;
    }

    public static Long getStampDateByDate(LocalDate localDate) {
        return localDate.atStartOfDay(ZoneOffset.of(getZoneStr(TIME_ZONE))).toInstant().toEpochMilli()/1000;
    }

    /**
     * 格式化时间为几天前 几秒前等
     *
     * @param localDateTime
     * @return
     */
    public static String dateDisPlayStr(LocalDateTime localDateTime) {
        Duration duration = Duration.between(localDateTime, LocalDateTime.now());
        long second = duration.getSeconds();
        if (second < 3) {
            return "刚刚";
        }
        if (second < 45L * ONE_MINUTE) {
            long minutes = toMinutes(second);
            return (minutes <= 0 ? 1 : minutes) + ONE_MINUTE_AGO;
        }
        if (second < 24L * ONE_HOUR) {
            long hours = toHours(second);
            return (hours <= 0 ? 1 : hours) + ONE_HOUR_AGO;
        }
        if (second < 48L * ONE_HOUR) {
            return "昨天";
        }
        if (second < 30L * ONE_DAY) {
            long days = toDays(second);
//            if (second <= 4L * ONE_DAY) {
            return (days <= 0 ? 1 : days) + ONE_DAY_AGO;
//            }
        }

        return LocalDateUtil.getDateFormatStr(localDateTime, SIMPLE_GANG_DATE);

    }

    /**
     * 转换成时间戳
     *
     * @param localDateTime
     * @return
     * 
     * @Date 5:20 下午 2020/12/2
     **/
    public static long toTimeMillis(LocalDateTime localDateTime) {
        return localDateTime.toInstant(ZoneOffset.of(getZoneStr(TIME_ZONE))).toEpochMilli();
    }

    /**
     * 获取市区
     *
     * @param timeZone
     * @return
     * 
     * @Date 5:35 下午 2020/12/2
     **/
    public static String getZoneStr(TimeZone timeZone) {
        int x = timeZone.getRawOffset() / (3600 * 1000);
        if (x >= 0) {
            return "+" + x;
        }
        return x + "";
    }

    /**
     * 将与微信交互的2021-02-01T10:20:31+08:00格式转换成指定格式
     *
     * @param wxTime
     * @param format
     * @return
     * 
     * @Date 5:35 下午 2020/12/2
     **/
    public static String getWxDateFormatStr(String wxTime, String format) {
        if (StrUtil.isEmpty(wxTime)) {
            return "";
        }

        String zoneStr = getTimeZone();

        String newTime = wxTime.replace(zoneStr, "");

        return DateFmtToOther(newTime, "yyyy-MM-dd'T'HH:mm:ss", format);
    }

    /**
     * 将时间转换成与微信交互的2021-02-01T10:20:31+08:00格式
     *
     * @return
     * 
     * @Date 5:35 下午 2020/12/2
     **/
    public static String strToWxDate(LocalDateTime dateTime) {
        if (ObjectUtil.isEmpty(dateTime)) {
            return "";
        }

        String zoneStr = getTimeZone();

        String dateFormatStr = getDateFormatStr(dateTime, "yyyy-MM-dd'T'HH:mm:ss");

        return dateFormatStr + zoneStr;
    }


    /**
     * 获取时区 比如 +08:00
     **/
    public static String getTimeZone() {
        Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"), Locale.getDefault());
        String timeZone = new SimpleDateFormat("Z").format(calendar.getTime());
        return "" + timeZone.substring(0, 3) + ":" + timeZone.substring(3, 5);
    }

    /**
     * 日期距离今天相差的年数
     * @param dateStr
     * @param format
     * @return
     */
    public static String getYearByDateStr(String dateStr, String format){
        if(!StrUtil.isAllNotEmpty(dateStr,format)){
            return "0";
        }

        DateTimeFormatter df = DateTimeFormatter.ofPattern(format);
        LocalDate localDateTime = LocalDate.parse(dateStr, df);

        LocalDateTime nowTime = LocalDateTime.now();
        int resultYear = nowTime.getYear() - localDateTime.getYear();
        return String.valueOf(resultYear);
    }

    private static long toMinutes(long date) {
        return date / 60L;
    }

    private static long toHours(long date) {
        return toMinutes(date) / 60L;
    }


    private static long toDays(long date) {
        return toHours(date) / 24L;
    }

    /**
     * 获取中央时区时间
     * @return
     */
    public static String getUTCDate() {
        LocalDateTime localDate = LocalDateTime.now(ZoneOffset.UTC);
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
        String time = dateTimeFormatter.format(localDate);
        return time;
    }
    public static void main(String[] args) {
//        String wxDateFormatStr = getWxDateFormatStr("2021-02-01T10:20:31+08:00", "yyyy-MM-dd HH:mm:ss");
//        String wxDateFormatStr = strToWxDate(LocalDateTime.now());
//        System.out.println(wxDateFormatStr);

        LocalDate localDate = LocalDateUtil.getNowAddDays(-1).toLocalDate();
        Long nowByDate = getStampDateByDate(getNowAddDays(0).toLocalDate());

        String fmtUTC = getLongToLocalDateTimeFmtUTC(1647254187101L);
        LocalDateTime yearByDateStr =LocalDateUtil.getLongToLocalDateTime(1647254187101L);

        System.out.println(yearByDateStr);
    }
}
